#ifndef MYOPENGLRENDER_H
#define MYOPENGLRENDER_H

#include "systemHead.h"
#include "ffmpegdecode.h"

enum point {x = 0, y, z, u, v};


struct CCVert{
    float x;
    float y;
    float z;
    float u;
    float v;
};

class Attritute{
private:
    QString             _attrituteName;
    QOpenGLShaderProgram        &_shader;
public:
    Attritute(const QString &attrituteName, QOpenGLShaderProgram &shader)
        :_attrituteName(attrituteName)
         , _shader(shader)
    {
        _shader.enableAttributeArray(attrituteName.toLocal8Bit().constData());
    }
    ~Attritute()
    {
        _shader.disableAttributeArray(_attrituteName.toLocal8Bit().constData());
    }
};

class BindText{
public:
    BindText(GLuint i)
    {
        glBindTexture(GL_TEXTURE_2D, i);
    }
    ~BindText()
    {
        glBindTexture(GL_TEXTURE_2D, 0);
    }
};


class StartShader{
private:
    QOpenGLShaderProgram        &_shader;
public:
    explicit StartShader(QOpenGLShaderProgram &shader)
        :_shader(shader)
    {
        _shader.bind();
    }
    ~StartShader()
    {
        _shader.release();
    }
};


class FBOThread;

struct unique_wrap{
    std::unique_ptr<H264Frame> _content = nullptr;
};


class MyOpenGLRender:public QOpenGLWidget, public QOpenGLExtraFunctions
{
    Q_OBJECT
public:
    friend FBOThread;
    MyOpenGLRender(QWidget *parent = nullptr);
    virtual ~MyOpenGLRender();
    void render(std::unique_ptr<H264Frame> frame);
    //避免残留前一个视频的画面
    void reset()
    {
        _once = true;
    }
private:
    void errPrint(const QString &InforMation);
private:
    void paintGL() override;
    void initializeGL() override;
    void resizeGL(int w, int h) override;
    void initShaderProgrem();
    void initFBO();
    void initPBO();
    void initTexture();
    void updatePBO(/*std::array<GLuint, 3> */GLuint pbo, /*std::array<GLuint, 3>*/GLuint pbo2, H264Frame *content);
    void renderContent(H264Frame *frame);
    void renderContent2(H264Frame *frame);
    void renderContent3(H264Frame *frame);
    void updatePBO2(std::array<GLuint, 3> pbo, std::array<GLuint, 3> pbo2, H264Frame *content);
private:
    GLuint                                      _pbo, _pbo2;
    GLuint                                      _vbo;
    GLuint                                      _fbo, _fboRender, _fboTexture;
    std::unordered_map<QString, GLuint>         _texture;
    QOpenGLShaderProgram                        _shaderprogram;
    std::unique_ptr<H264Frame>                  _renderContent = nullptr;
    GLuint                                      _pboArry[6];
//    std::deque<std::unique_ptr<H264Frame>>      _renderContentList;
    std::mutex                                  _renderMutex;
    bool                                        _once = true;
//    QOpenGLContext                          *_firstContext = nullptr;
//    decltype (_firstContext->surface())     _mainSurface = nullptr, _offSurface = nullptr;

};

//class FBORender:public QOpenGLWidget, public QOpenGLExtraFunctions
//{
//    Q_OBJECT
//public:
//    FBORender(QWidget *parent = nullptr, MyOpenGLRender *render = nullptr);
//    void Render(H264Frame * content);
//private:
//    void paintGL() override;
//    void initializeGL() override;
//    void resizeGL(int w, int h) override;
//private:
//    MyOpenGLRender              *_render;
//    QOpenGLContext              *_secondContext = nullptr;
//};

//class FBOThread:public QThread,public QOpenGLExtraFunctions
//{
//    Q_OBJECT
//public:
//    FBOThread(QObject *parent = nullptr, MyOpenGLRender *render = nullptr);
//    virtual ~FBOThread();
//    void PushElement(H264Frame *ele);
//private:
//    void run() override;
//private:
//    MyOpenGLRender              *_render;
//    QLinkedList<H264Frame*>     _list;
//    QOpenGLContext              *_secondContext = nullptr;

//};



#endif // MYOPENGLRENDER_H
